/*
 * @Author: yangzonglong
 * @Date: 2021-03-03 14:44:59
 * @version: v1.0.0
 * @Descripttion: Input 控制器
 * @LastEditors: Please set LastEditors
 * @LastEditTime: 2021-10-20 15:50:29
 * @Auditor:
 */
import React, { useState, useEffect, useMemo, useCallback, useRef } from 'react';
import { Form, Input, Button, Checkbox } from 'antd';
import { Select } from '@library';
import useFdStore from '../../../hooks/useFdStore';
import { flatControl } from '../../../util';
import { ChangeForData } from '../../../config';
import Columns from './columns/Columns';
import Sorts from './sorts/Sorts';
import { getTableShowComponentsArray, getModel, getModels, companyModelItf } from '../../../util';
import update from 'immutability-helper';
import CommonController from '../CommonController';
import ScreenModal from '../../components/optionSetting/screenModal/ScreenModal';
import ScreenModalRule from '../../components/optionSetting/screenModal/ScreenModalRules';
import styles from './style.module.scss';

let cacheData = {};
// const linkType = ['dataLink', 'dataLinkCombox', 'dataLinkComBox'];
const FormItem = Form.Item;
const FieldNames = { label: 'label', value: 'value' };
const ftStyle = { marginBottom: '8px' };
const dfDataSource = [
  { label: 'APP', value: 'APP', id: '2' },
  { label: 'API', value: 'API', id: '1' },
];
let urlSourceObj: any = {}; // 缓存api类型下的url对应的字段

interface UrlProps {
  label: string;
  value: string;
  id: string;
}

const Controller = (props: any) => {
  const {
    tableProps,
    dataSource,
    print,
    required,
    originalIndex,
    dataIndex,
    columns,
    placeholder,
    placeholderEn,
    serviceType,
    serviceModuleCode,
    modulesUrl,
    modulesName,
    filedShowName,
    fieldNames,
    screenCondition,
    showFieldName,
    sortNames,
    title,
    titleEn,
    width,
    disabled,
    exportFlag,
    radio,
    changeColumnOptions,
    changeControlProps,
    setCurColumn,
    screenConditionRules,
    keyValue,
    bindName,
    extraFieldName,
    fontSize,
    fontWeight,
    backgroundColor,
    color,
    customizeStyleFlag,
    treeStructure,
    treeId,
    treeParentId
  } = props;

  const {
    state: { list },
  } = useFdStore();

  const name = columns?.[originalIndex]?.['key'] || '';
  const appFlag = useRef<boolean>(false);
  const apiFlag = useRef<boolean>(false);
  const dataObj = useRef({});
  const mapFileds = useRef<any>({});
  const [visible, setVisible] = useState(false);
  const [ruleVisible, setRuleVisible] = useState(false);
  const [modelsSource, setModelsSource] = useState([]);
  const [modelSource, setModelSource] = useState<any[]>([]);
  const [urlSource, setUrlSource] = useState<UrlProps[]>([]);
  const [bindmoduleName, setBindmoduleName] = useState<any[]>([]);

  const showComponentsArray = useMemo(() => {
    const { dataObj: _dataObj, list: _list } = getTableShowComponentsArray({ columns, dataIndex, keyValue, list: flatControl(list || []) });
    dataObj.current = _dataObj;
    return _list;
  }, [columns, dataIndex, keyValue, list]);

  useEffect(() => {
    let _temp = columns.filter((item: any) => (item.dataIndex === bindName || item.key === bindName));
    if (_temp.length) {
      setBindmoduleName(_temp[0]?.['options']?.['filedShowName'] || []);
    }
  }, [bindName, columns]);

  useEffect(() => {
    let _temp = flatControl(list || []).filter((item) => item?.options?.formItemProps?.name === bindName);
    if (_temp.length) {
      setBindmoduleName(_temp[0]?.options?.inputProps?.filedShowName || []);
    }
  }, [list, bindName]);

  const ISAPI = useMemo(() => serviceType === 'API', [serviceType]);

  const onChangeColumnOptions = useCallback(
    (e: any, k: string, isChecked?: boolean) => {
      changeColumnOptions(k, isChecked ? e.target.checked : e.target.value, originalIndex);
    },
    [changeColumnOptions, originalIndex]
  );

  const onOK = useCallback(
    (data) => {
      setVisible(false);
      changeColumnOptions('', { screenCondition: data }, originalIndex);
    },
    [changeColumnOptions, originalIndex]
  );

  const onRuleOK = useCallback(
    (data) => {
      setRuleVisible(false);
      changeColumnOptions('', { screenConditionRules: data }, originalIndex);
    },
    [changeColumnOptions, originalIndex]
  );

  const _changeControlProps = useCallback(
    (e: any, k: string, isChecked?: boolean) => {
      console.log(isChecked, e.target);
      changeControlProps(
        'tableProps',
        {
          ...tableProps,
          columns: update(columns!, {
            [originalIndex!]: {
              [k]: {
                $set: isChecked ? e.target.checked : e?.target?.value || (typeof e === 'object' ? '' : e),
              },
            },
          }),
          dataSource: { $set: dataSource },
        },
        true
      );
      setCurColumn?.({ ...columns![originalIndex!], originalIndex, [k]: isChecked ? e.target.checked : e?.target?.value || (typeof e === 'object' ? '' : e) });
    },
    [changeControlProps, tableProps, columns, originalIndex, dataSource, setCurColumn]
  );

  const onServiceTypeChange = useCallback(
    (serviceType) => {
      cacheData = {};
      urlSourceObj = {};
      setModelsSource([]);
      setModelSource([]);
      setUrlSource([]);
      // 清除各个缓存source
      changeColumnOptions(
        '',
        {
          serviceType,
          ...ChangeForData.serviceType,
        },
        originalIndex
      );
    },
    [changeColumnOptions, originalIndex]
  );

  useEffect(() => {
    // app逻辑

    if (serviceType !== 'APP') return;

    if (!serviceModuleCode) return;

    if (!cacheData[name + 'ModelsSource'] && !appFlag.current) {
      appFlag.current = true;
      getModels(serviceModuleCode)
        .then((res) => {
          appFlag.current = false;
          let _res = res?.map((item: string) => ({ label: item, value: item }));
          cacheData[name + 'ModelsSource'] = _res;
          setModelsSource(_res);
        })
        .catch((err) => {
          appFlag.current = false;
        });
    } else if (cacheData[name + 'ModelsSource']) {
      setModelsSource(cacheData[name + 'ModelsSource'] || []);
    }

    if (!modulesName) return;

    if (!cacheData[name + 'ModelSource']) {
      getModel(serviceModuleCode, modulesName).then((res) => {
        cacheData[name + 'ModelSource'] = res;
        setModelSource(res);
      });
    } else if (cacheData[name + 'ModelSource']) {
      setModelSource(cacheData[name + 'ModelSource'] || []);
    }
  }, [modulesName, name, serviceModuleCode, serviceType]);

  useEffect(() => {
    // API逻辑
    if (serviceType !== 'API') return;

    if (!serviceModuleCode) return;

    if (!cacheData[name + 'UrlSource'] && !apiFlag.current) {
      apiFlag.current = true;
      companyModelItf(serviceModuleCode)
        .then((res) => {
          apiFlag.current = false;
          let _res = res?.map((item, index) => ({ label: item.itfApi, value: item.itfApi, id: item.itfApi + index }));

          cacheData[name + 'UrlSource'] = _res;
          urlSourceObj = {};

          res?.forEach((item) => {
            urlSourceObj[item.itfApi] = (item?.CompanyModelItfParams || []).map((item: any) => ({ label: item.paramName, value: item.paramField }));
          });

          res?.forEach((item) => {
            let _mapFiled: any = {};
            if (item.mappingEnableFlag) {
              (item?.CompanyModelItfParams || []).forEach((ele: any) => {
                _mapFiled[ele.paramField] = ele.mapField;
              });
              mapFileds.current[item.itfApi] = _mapFiled;
            }
          });

          setUrlSource(_res);

          if (modulesUrl) {
            setModelSource(urlSourceObj[modulesUrl] || []);
          }
        })
        .catch((err) => {
          apiFlag.current = false;
        });
    } else if (cacheData[name + 'UrlSource']) {
      setUrlSource(cacheData[name + 'UrlSource'] || []);
    }

    if (modulesUrl) {
      setModelSource(urlSourceObj[modulesUrl] || []);
    }
  }, [modulesUrl, name, serviceModuleCode, serviceType]);

  return (
    <CommonController
      onChangeControlProps={_changeControlProps}
      onChangeColumnOptions={onChangeColumnOptions}
      showIsRadio
      {...{ title, titleEn, dataIndex, width, required, print, disabled, exportFlag, radio, fontSize, fontWeight, backgroundColor, color, customizeStyleFlag }}
    >

      <FormItem label="提示">
        <Input onChange={(e) => changeColumnOptions('placeholder', e.target.value, originalIndex)} value={placeholder} />
      </FormItem>

      <FormItem label="英文提示">
        <Input onChange={(e) => changeColumnOptions('placeholderEn', e.target.value, originalIndex)} value={placeholderEn} />
      </FormItem>

      <FormItem label="关联设置" tooltip="关联设置">
        <FormItem>
          <Select
            style={ftStyle}
            value={serviceType}
            onChange={(e: any) => onServiceTypeChange(e.value)}
            dataSource={dfDataSource}
            fieldNames={FieldNames}
            url=""
            placeholder="请选择关联类型"
          />
        </FormItem>

        {ISAPI ? (
          <>
            <FormItem>
              <Select
                style={ftStyle}
                value={serviceModuleCode}
                onChange={async (e: any) => {
                  changeColumnOptions(
                    '',
                    {
                      serviceModuleCode: e.value,
                      ...ChangeForData.serviceModuleCode,
                    },
                    originalIndex
                  );
                  const res = await companyModelItf(e.value);

                  res?.forEach((item) => {
                    urlSourceObj[item.itfApi] = (item?.CompanyModelItfParams || []).map((item: any) => ({ label: item.paramName, value: item.paramField }));
                  });

                  res?.forEach((item) => {
                    let _mapFiled: any = {};
                    if (item.mappingEnableFlag) {
                      (item?.CompanyModelItfParams || []).forEach((ele: any) => {
                        _mapFiled[ele.paramField] = ele.mapField;
                      });
                      mapFileds.current[item.itfApi] = _mapFiled;
                    }
                  });

                  setUrlSource(res?.map((item, index) => ({ label: item.itfApi, value: item.itfApi, id: item.itfApi + index })));
                }}
                fieldNames={{ label: 'serviceModuleName', value: 'serviceModuleCode' }}
                url="/bk/mid/companyx/findModule"
                placeholder="请选择关联应用"
              />
            </FormItem>

            <FormItem>
              <Select
                style={ftStyle}
                value={modulesUrl}
                onChange={(e: any) => {
                  changeColumnOptions(
                    '',
                    {
                      modulesUrl: e.value,
                      fieldNames: urlSourceObj[e.value] || [],
                      mapFileds: mapFileds.current[e.value] || {},
                      ...ChangeForData.modulesUrl,
                    },
                    originalIndex
                  );
                }}
                fieldNames={FieldNames}
                url=""
                dataSource={urlSource}
                placeholder="请选择数据接口"
              />
            </FormItem>
          </>
        ) : (
          <>
            <FormItem>
              <Select
                style={ftStyle}
                value={serviceModuleCode}
                onChange={(e: any) => {
                  cacheData[name + 'ModelsSource'] = undefined;
                  cacheData[name + 'ModelSource'] = undefined;
                  changeColumnOptions(
                    '',
                    {
                      serviceModuleCode: e.value,
                      ...ChangeForData.serviceModuleCode,
                    },
                    originalIndex
                  );
                }}
                fieldNames={{ label: 'serviceModuleName', value: 'serviceModuleCode' }}
                url="/bk/mid/companyx/findModule"
                placeholder="请选择关联应用"
              />
            </FormItem>

            <FormItem>
              <Select
                style={ftStyle}
                value={modulesName}
                onChange={async (e: any) => {
                  const res = e.value && (await getModel(serviceModuleCode, e.value));
                  cacheData[name + 'ModelSource'] = res;
                  changeColumnOptions('', { modulesName: e.value, fieldNames: res, ...ChangeForData.modulesName }, originalIndex);
                }}
                fieldNames={FieldNames}
                url=""
                dataSource={modelsSource}
                placeholder="请选择数据模型"
              />
            </FormItem>
          </>
        )}

        <div>
          <Select
            mode='multiple'
            value={(showFieldName ? Array.isArray(showFieldName) ? showFieldName : [{ value: showFieldName, label: showFieldName }] : []) as any}
            onChange={(e: any) => changeColumnOptions('', { showFieldName: e.map((item: any) => ({ value: item.value, label: item.label })) }, originalIndex)}
            fieldNames={FieldNames}
            url=""
            dataSource={modelSource}
            placeholder="请选择展示字段"
          />
        </div>

        <Columns dataSource={modelSource} changeControlProps={(filedShowName) => {
          changeColumnOptions('', { filedShowName }, originalIndex);
        }} columns={filedShowName || []} />

        <Columns title='请选择扩展字段' dataSource={modelSource} changeControlProps={(extraFieldName) => {
          changeColumnOptions('', { extraFieldName }, originalIndex);
        }} columns={extraFieldName || []} />

      </FormItem>

      <FormItem label="筛选数据">
        <Button className={styles.btnStyle} block onClick={() => setVisible(true)}>
          设置筛选数据
        </Button>
      </FormItem>

      <Sorts dataSource={modelSource} changeControlProps={(sortNames) => {
        changeColumnOptions(
          '',
          { sortNames },
          originalIndex
        );
      }} columns={sortNames || []} />

      <FormItem label="关联已有数据">
        <Select
          value={bindName}
          allowClear
          onClear={() => {
            changeColumnOptions('', { bindName: undefined, screenConditionRules: [] }, originalIndex);
            setBindmoduleName([]);
          }}
          onSelect={(e: any) => {
            changeColumnOptions('', { bindName: e, screenConditionRules: [] }, originalIndex);
            setBindmoduleName(dataObj.current?.[e] || []);
          }}
          dataSource={showComponentsArray}
          fieldNames={FieldNames}
          url=""
          placeholder="请选择组件"
        />
      </FormItem>

      <FormItem label="筛选条件" tooltip="待填写">
        <Button className={styles.btnStyle} block onClick={() => setRuleVisible(true)}>
          设置筛选条件
        </Button>
      </FormItem>

      <FormItem className='antd-form-item-row' label="树结构" >
        <Checkbox onChange={(e) => changeColumnOptions('treeStructure', e.target.checked)} checked={treeStructure} />
      </FormItem>

      {treeStructure &&
        <>
          <FormItem label="ID" tooltip="父元素的子数据关联属性">
            <Input value={treeId} onChange={e => { changeColumnOptions('treeId', e.target.value); }} />
          </FormItem>
          <FormItem label="ParentID" tooltip="子数据关联父元素的属性">
            <Input value={treeParentId} onChange={e => { changeColumnOptions('treeParentId', e.target.value); }} />
          </FormItem>
        </>}

      <ScreenModal
        fieldNames={fieldNames || []}
        dataSource={screenCondition || []}
        visible={visible}
        onOK={onOK}
        onCancel={() => setVisible(false)}
      />

      <ScreenModalRule
        fieldNames={fieldNames || []}
        bindmoduleName={bindmoduleName}
        dataSource={screenConditionRules || []}
        visible={ruleVisible}
        onOK={onRuleOK}
        onCancel={() => setRuleVisible(false)}
      />

    </CommonController>
  );
};

export default Controller;
